package com.huangyi.portalservice.homepage.service.impl;


import com.huangyi.adminapi.config.feign.DictionaryFeignClient;
import com.huangyi.adminapi.house.domain.dto.SearchHouseListReqDTO;
import com.huangyi.adminapi.house.domain.vo.HouseDetailVO;
import com.huangyi.adminapi.house.feign.HouseFeignClient;
import com.huangyi.adminapi.map.domain.dto.LocationReqDTO;
import com.huangyi.adminapi.map.domain.vo.RegionCityVo;
import com.huangyi.adminapi.map.feign.MapFeignClient;
//import com.huangyi.adminservice.house.service.impl.HouseServiceImpl;
import com.huangyi.commoncore.utils.BeanCopyUtil;
import com.huangyi.commoncore.utils.JsonUtil;
import com.huangyi.commondomain.domain.R;
import com.huangyi.commondomain.domain.ResultCode;
import com.huangyi.commondomain.domain.vo.BasePageVO;
import com.huangyi.commondomain.exception.ServiceException;
import com.huangyi.commonredis.service.RedisService;
import com.huangyi.portalservice.homepage.domain.dto.CityDescDTO;
import com.huangyi.portalservice.homepage.domain.dto.DictDataDTO;
import com.huangyi.portalservice.homepage.domain.dto.HouseListReqDTO;
import com.huangyi.portalservice.homepage.domain.dto.PullDataListReqDTO;
import com.huangyi.portalservice.homepage.domain.vo.CityDescVO;
import com.huangyi.portalservice.homepage.domain.vo.DictsVO;
import com.huangyi.portalservice.homepage.domain.vo.HouseDescVO;
import com.huangyi.portalservice.homepage.domain.vo.PullDataListVO;
import com.huangyi.portalservice.homepage.service.IDictionaryService;
import com.huangyi.portalservice.homepage.service.IHomePageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 首页服务实现类
 * 
 * <p>实现首页相关的业务功能，包括城市信息获取、筛选数据获取和房源列表查询
 * 
 * @author huangyi
 * @version 1.0
 * @since 2024
 */
@Service
@Slf4j
public class HomePageServiceImpl implements IHomePageService {

    /** 地图服务Feign客户端 */
    @Autowired
    private MapFeignClient mapFeignClient;

    /** 字典服务Feign客户端 */
    @Autowired
    private DictionaryFeignClient dictionaryFeignClient;

    /** Redis服务 */
    @Autowired
    private RedisService redisService;

    /** 区域服务实现类 */
    @Autowired
    private RegionServiceImpl regionServiceImpl;

    /** 字典服务实现类 */
    @Autowired
    private IDictionaryService dictionaryServiceImpl;

    /** 房源服务Feign客户端 */
    @Autowired
    private HouseFeignClient houseFeignClient;

    /**
     * 根据经纬度获取城市信息
     * 
     * @param lat 纬度
     * @param lng 经度
     * @return 城市信息DTO
     */
    @Override
    public CityDescDTO getCityDesc(Double lat, Double lng) {
        // 校验参数
        if(lat == null || lng == null){
            throw new ServiceException("城市经纬度不能为空", ResultCode.INVALID_PARA.getCode());
        }
        if (lat< -90 || lat > 90) {
            throw new ServiceException("经度非法", ResultCode.INVALID_PARA.getCode());
        }
        if (lng < -180 || lng > 180){
            throw new ServiceException("维度非法", ResultCode.INVALID_PARA.getCode());
        }

        // 调用 Feign
        LocationReqDTO locationReqDTO = new LocationReqDTO();
        locationReqDTO.setLat(lat);
        locationReqDTO.setLng(lng);
        R<RegionCityVo> regionCityVoR =  mapFeignClient.locateCityByLocation(locationReqDTO);
        if(regionCityVoR == null || regionCityVoR.getCode() != ResultCode.SUCCESS.getCode() || regionCityVoR.getData() == null){
            throw new ServiceException("根据定位获取城市失败", ResultCode.INVALID_PARA.getCode());
        }

        // 转换实例类
        RegionCityVo regionCityVo = regionCityVoR.getData();
        CityDescDTO result = new CityDescDTO();
        BeanUtils.copyProperties(regionCityVo, result);

        return result;

    }

    /**
     * 获取下拉筛选数据列表
     * 
     * @param reqDTO 筛选数据请求参数
     * @return 筛选数据列表视图对象
     */
    @Override
    public PullDataListVO getPullDataList(PullDataListReqDTO reqDTO) {

        PullDataListVO result = new PullDataListVO();

        // 查询城市下区域列表 (Redis, MySQL)
        List<CityDescDTO> cityDescVOList =
                regionServiceImpl.regionChildren(reqDTO.getCityId());
        if(cityDescVOList == null || cityDescVOList.isEmpty()){
            log.error("查询城市下区域列表为空, 请检查入参！");
        }
        result.setRegionList(
                BeanCopyUtil.copyListProperties(cityDescVOList,CityDescVO::new));


        // 查询字典类型查字典数据
        Map<String, List<DictDataDTO>> listMap =  dictionaryServiceImpl.batchFindDictionaryDataByTypes(reqDTO.getDirtTypes());
        if(listMap == null || listMap.isEmpty()){
            log.error("根据字典类型查询字典数据为空, 请检查入参！");
        }
        Map<String, List<DictsVO>> tmpMap = new HashMap<String, List<DictsVO>>();
        for (Map.Entry<String, List<DictDataDTO>> entry : listMap.entrySet()) {
            List<DictsVO> tmplist = entry.getValue().stream()
                    .map(entryDTO ->{
                        DictsVO dictsVO = new DictsVO();
                        dictsVO.setId(entryDTO.getId());
                        dictsVO.setName(entryDTO.getValue());
                        dictsVO.setKey(entryDTO.getDataKey());
                        return dictsVO;
                    }).collect(Collectors.toList());
            tmpMap.put(entry.getKey(), tmplist);

        }
        result.setDictMap(tmpMap);

        // 组装构造返回
        return  result;
    }

    /**
     * 查询房源列表
     * 
     * @param reqDTO 房源列表查询请求参数
     * @return 房源列表分页视图对象
     */
    @Override
    public BasePageVO<HouseDescVO> houseList(HouseListReqDTO reqDTO) {
        BasePageVO<HouseDescVO> result = new BasePageVO<>();
        // 查询 feign 接口获取房源列表
        SearchHouseListReqDTO searchHouseListReqDTO = new SearchHouseListReqDTO();
        BeanUtils.copyProperties(reqDTO, searchHouseListReqDTO);
        R<BasePageVO<HouseDetailVO>> r = houseFeignClient.searchList(searchHouseListReqDTO);
        if(r == null || r.getData() == null || r.getCode() != ResultCode.SUCCESS.getCode()){
            log.error("查询房源列表操作失败！ reqDTO:{}", JsonUtil.obj2String(reqDTO));
            throw new ServiceException("查询房源列表操作失败！", ResultCode.INVALID_PARA.getCode());
        }


        // 查字典构造返回
        result.setTotals(r.getData().getTotals());
        result.setTotalPages(r.getData().getTotalPages());
        result.setList(convertHouseList(r.getData().getList()));
        return result;
    }

    /**
     * 转换房源详情列表为房源描述列表
     * 
     * @param houseDetailVOS 房源详情列表
     * @return 房源描述列表
     */
    public List<HouseDescVO> convertHouseList(List<HouseDetailVO> houseDetailVOS) {
        // 判断空
        if(CollectionUtils.isEmpty(houseDetailVOS)){
            log.error("查字典构造返回操作错误！ houseDetailVOS:{}", JsonUtil.obj2String(houseDetailVOS));
            return Arrays.asList();
        }

        List<HouseDescVO> result = new ArrayList<>();
        // list 存储的是 data_key, 前段需要返回 value, 所以要查字典 rentType, position
        List<String> dataKeyList = houseDetailVOS.stream()
                .flatMap(houseDetailVO -> Stream.of(houseDetailVO.getRentType(), houseDetailVO.getPosition()))
                .distinct()
                .collect(Collectors.toList());

        // 根据字典数据keys获取字典数据, 如果指直接在这个地方调用  dictionaryFeign 就会造成代码冗余
        Map<String, DictDataDTO> dictDataDTOMap = dictionaryServiceImpl.batchFindDictionaryData(dataKeyList);
        result = houseDetailVOS.stream()
                .map(houseDetailVO -> {
                    HouseDescVO houseDescVO = new HouseDescVO();
                    houseDescVO.setHouseId(houseDetailVO.getHouseId());
                    houseDescVO.setHeadImage(houseDetailVO.getHeadImage());
                    houseDescVO.setTitle(houseDetailVO.getTitle());
                    houseDescVO.setArea(houseDetailVO.getArea());
                    houseDescVO.setRegionName(houseDetailVO.getRegionName());
                    houseDescVO.setPrice(houseDetailVO.getPrice());

                    // 从 dictDataDTOMap 中拿取英文与汉字, data_key 与 value 的映射, get 拿到映射关系, getValue 拿到值
                    houseDescVO.setRentType(dictDataDTOMap
                            .get(houseDetailVO.getRentType())
                            .getValue());
                    houseDescVO.setPosition(dictDataDTOMap
                            .get(houseDetailVO.getPosition())
                            .getValue());
                    return houseDescVO;
                }).collect(Collectors.toList());

        return result;
    }

}
